package com.ajk.server.config;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.AntPathMatcher;

import com.ajk.server.model.UserRole;
import com.ajk.server.security.AjkAuthenticationFilter;


@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan("com.ajk.server.security")
public class RestSecurityConfiguration extends WebSecurityConfigurerAdapter {
	public static AntPathMatcher antMatcher = new AntPathMatcher();
	public static boolean matchPermitAll(String path){
		if(pathMap!=null && !pathMap.isEmpty()){
			for(Entry<String, Integer> entry : pathMap.entrySet()){
				if(antMatcher.match(entry.getKey(), path)){
					if(entry.getValue()==CNT_ALL){
						return true;
					}
				}
			}
		}
		return false;
	}

	private static AjkAuthenticationFilter ajkAuthenticationFilter = new AjkAuthenticationFilter();
	public static Map<String, Integer> pathMap = new LinkedHashMap<String, Integer>();
	public static int CNT_PATIENT = 1;
	public static int CNT_DOCTOR=2;
	public static int CNT_ADMIN=4;
	public static int CNT_ALL = 8;
	static{  //添加的时候注意一下排序，字母倒叙的顺序添加
		pathMap.clear();
		pathMap.put("/account/reset_password",CNT_PATIENT|CNT_ADMIN|CNT_DOCTOR);
		pathMap.put("/questionnaire/patients/submit_paper/**",CNT_ALL);
		pathMap.put("/questionnaire/patients/**",CNT_PATIENT|CNT_ADMIN|CNT_DOCTOR);
		pathMap.put("/easemod/**",CNT_PATIENT|CNT_ADMIN|CNT_DOCTOR);
		pathMap.put("/admin/**", CNT_ADMIN);
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// Disable CSRF detection
		http.csrf().disable();

		// Disable session so that every request needs to carry authentication information
		http.sessionManagement()
		.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
		http.addFilterBefore(ajkAuthenticationFilter, BasicAuthenticationFilter.class);
		if(pathMap!=null && !pathMap.isEmpty()){
			for(Entry<String, Integer> entry : pathMap.entrySet()){
				if(entry.getValue()==CNT_PATIENT){
					http.authorizeRequests().antMatchers(entry.getKey()).hasAuthority(UserRole.PATIENT.name());
				}else if(entry.getValue()==CNT_DOCTOR){
					http.authorizeRequests().antMatchers(entry.getKey()).hasAuthority(UserRole.DOCTOR.name());
				}else if(entry.getValue()==CNT_ADMIN){
					http.authorizeRequests().antMatchers(entry.getKey()).hasAuthority(UserRole.ADMIN.name());
				}else if(entry.getValue()==CNT_ALL){
					http.authorizeRequests().antMatchers(entry.getKey()).permitAll();
				}else{
					List<String> authoritiesList = new ArrayList<String>();
					if((entry.getValue()&CNT_PATIENT)==CNT_PATIENT){
						authoritiesList.add(UserRole.PATIENT.name());
					}
					if((entry.getValue()&CNT_DOCTOR)==CNT_DOCTOR){
						authoritiesList.add(UserRole.DOCTOR.name());
					}
					if((entry.getValue()&CNT_ADMIN)==CNT_ADMIN){
						authoritiesList.add(UserRole.ADMIN.name());
					}
					if(!authoritiesList.isEmpty()){
						String[] authorities = new String[authoritiesList.size()];
						for(int i=0; i<authoritiesList.size(); i++){
							authorities[i] = authoritiesList.get(i);
						}
						http.authorizeRequests().antMatchers(entry.getKey()).hasAnyAuthority(authorities);
					}
				}
			}
		}
		http.authorizeRequests();//.and().httpBasic();
	}
}